"""
📸 AIOT智能学习桌 - 摄像头坐姿检测模块 (完整增强版)

核心功能：
✅ AI智能坐姿检测 (MediaPipe + OpenCV)
✅ 多维度坐姿分析 (头部、肩膀、背部、颈部)
✅ 实时坐姿评分和建议
✅ 语音智能反馈系统
✅ 与超声波传感器联合检测
✅ 个性化坐姿适应学习
✅ 数据存储和历史分析
✅ 微信小程序实时同步
✅ 疲劳检测和休息提醒

硬件依赖：
- USB摄像头 (30万像素以上)
- 计算设备 (用于AI推理)
- 网络连接 (用于数据同步)

软件依赖：
- OpenCV 4.0+
- MediaPipe
- NumPy
- scikit-learn
- requests

作者: AIOT智能学习桌项目组
版本: v2.0 AI增强版
"""

import cv2
import mediapipe as mp
import numpy as np
import time
import json
import requests
import threading
import queue
import logging
import sqlite3
import os
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Optional, NamedTuple
from dataclasses import dataclass
from collections import deque
import math
import serial
import asyncio
import websockets

# 配置日志系统
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/camera_posture.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# ========== 配置参数 ==========
class PostureConfig:
    """坐姿检测配置参数"""
    
    # 摄像头配置
    CAMERA_ID = 0
    FRAME_WIDTH = 640
    FRAME_HEIGHT = 480
    FPS = 30
    
    # MediaPipe配置
    MODEL_COMPLEXITY = 1
    MIN_DETECTION_CONFIDENCE = 0.7
    MIN_TRACKING_CONFIDENCE = 0.5
    SMOOTH_LANDMARKS = True
    
    # 坐姿评估阈值
    HEAD_TILT_THRESHOLD = 15.0          # 头部倾斜角度阈值
    SHOULDER_LEVEL_THRESHOLD = 10.0     # 肩膀水平差阈值
    NECK_FORWARD_THRESHOLD = 30.0       # 颈部前倾阈值
    BACK_STRAIGHT_THRESHOLD = 160.0     # 背部挺直阈值
    EYE_ASPECT_RATIO_THRESHOLD = 0.25   # 眼睛疲劳检测阈值
    
    # 时间控制
    DETECTION_INTERVAL = 0.1           # 检测间隔(秒)
    WARNING_INTERVAL = 30.0            # 警告间隔(秒)
    ANALYSIS_WINDOW = 30               # 分析窗口(帧数)
    FATIGUE_CHECK_INTERVAL = 60.0      # 疲劳检测间隔(秒)
    
    # 数据存储
    MAX_HISTORY_RECORDS = 1000         # 最大历史记录数
    DATA_SAVE_INTERVAL = 300           # 数据保存间隔(秒)
    
    # 通信配置
    SERIAL_PORT = 'COM5'               # 串口端口
    SERIAL_BAUDRATE = 115200           # 串口波特率
    WECHAT_API_URL = 'ws://localhost:8080/smartdesk'  # 微信小程序WebSocket
    AI_API_URL = 'https://api.openai.com/v1/chat/completions'  # AI API
    AI_API_KEY = 'your-openai-api-key'  # AI API密钥

# ========== 数据结构定义 ==========

@dataclass
class PostureLandmarks:
    """坐姿关键点数据"""
    nose: Tuple[float, float]
    left_eye: Tuple[float, float]
    right_eye: Tuple[float, float]
    left_ear: Tuple[float, float]
    right_ear: Tuple[float, float]
    left_shoulder: Tuple[float, float]
    right_shoulder: Tuple[float, float]
    left_elbow: Tuple[float, float]
    right_elbow: Tuple[float, float]
    left_hip: Tuple[float, float]
    right_hip: Tuple[float, float]
    timestamp: float

@dataclass
class PostureMetrics:
    """坐姿度量数据"""
    head_tilt_angle: float              # 头部倾斜角度
    shoulder_level_diff: float          # 肩膀水平差
    neck_forward_angle: float           # 颈部前倾角度
    back_straightness: float            # 背部挺直度
    overall_score: float                # 总体得分
    confidence: float                   # 检测置信度
    timestamp: float

@dataclass
class PostureAnalysisResult:
    """坐姿分析结果"""
    status: str                         # 坐姿状态
    score: float                        # 坐姿得分
    issues: List[str]                   # 问题列表
    suggestions: List[str]              # 建议列表
    severity: str                       # 严重程度
    voice_feedback: str                 # 语音反馈
    need_warning: bool                  # 是否需要警告
    timestamp: float

@dataclass
class FatigueMetrics:
    """疲劳检测数据"""
    eye_aspect_ratio: float             # 眼睛纵横比
    blink_frequency: float              # 眨眼频率
    head_stability: float               # 头部稳定性
    attention_level: float              # 注意力水平
    fatigue_score: float                # 疲劳得分
    timestamp: float

# ========== 核心检测类 ==========

class CameraPostureDetector:
    """摄像头坐姿检测器"""
    
    def __init__(self, config: PostureConfig = None):
        """初始化检测器"""
        self.config = config or PostureConfig()
        
        # MediaPipe初始化
        self.mp_pose = mp.solutions.pose
        self.mp_face_mesh = mp.solutions.face_mesh
        self.mp_drawing = mp.solutions.drawing_utils
        
        self.pose = self.mp_pose.Pose(
            static_image_mode=False,
            model_complexity=self.config.MODEL_COMPLEXITY,
            smooth_landmarks=self.config.SMOOTH_LANDMARKS,
            enable_segmentation=False,
            min_detection_confidence=self.config.MIN_DETECTION_CONFIDENCE,
            min_tracking_confidence=self.config.MIN_TRACKING_CONFIDENCE
        )
        
        self.face_mesh = self.mp_face_mesh.FaceMesh(
            static_image_mode=False,
            max_num_faces=1,
            refine_landmarks=True,
            min_detection_confidence=self.config.MIN_DETECTION_CONFIDENCE,
            min_tracking_confidence=self.config.MIN_TRACKING_CONFIDENCE
        )
        
        # 状态变量
        self.is_running = False
        self.cap = None
        self.frame_count = 0
        self.last_detection_time = 0
        self.last_warning_time = 0
        self.last_fatigue_check = 0
        
        # 数据存储
        self.landmark_history = deque(maxlen=self.config.ANALYSIS_WINDOW)
        self.metrics_history = deque(maxlen=self.config.MAX_HISTORY_RECORDS)
        self.fatigue_history = deque(maxlen=100)
        
        # 通信组件
        self.serial_connection = None
        self.websocket_connection = None
        self.communication_queue = queue.Queue()
        
        # AI分析引擎
        self.ai_analyzer = AIPostureAnalyzer()
        
        # 个性化适应器
        self.personalization_engine = PersonalizationEngine()
        
        # 数据库连接
        self.db_path = 'data/posture_data.db'
        self.init_database()
        
        logger.info("📸 摄像头坐姿检测器初始化完成")

    def init_database(self):
        """初始化数据库"""
        os.makedirs(os.path.dirname(self.db_path), exist_ok=True)
        
        with sqlite3.connect(self.db_path) as conn:
            cursor = conn.cursor()
            
            # 创建坐姿记录表
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS posture_records (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    timestamp REAL,
                    head_tilt REAL,
                    shoulder_diff REAL,
                    neck_forward REAL,
                    back_straight REAL,
                    overall_score REAL,
                    status TEXT,
                    suggestions TEXT,
                    need_warning BOOLEAN
                )
            ''')
            
            # 创建疲劳记录表
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS fatigue_records (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    timestamp REAL,
                    eye_ratio REAL,
                    blink_freq REAL,
                    head_stability REAL,
                    attention_level REAL,
                    fatigue_score REAL
                )
            ''')
            
            # 创建会话记录表
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS session_records (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    session_start REAL,
                    session_end REAL,
                    total_detections INTEGER,
                    average_score REAL,
                    warning_count INTEGER,
                    fatigue_events INTEGER
                )
            ''')
            
            conn.commit()
        
        logger.info("📊 数据库初始化完成")

    def start_detection(self) -> bool:
        """启动检测"""
        try:
            # 初始化摄像头
            self.cap = cv2.VideoCapture(self.config.CAMERA_ID)
            if not self.cap.isOpened():
                logger.error("❌ 无法打开摄像头")
                return False
            
            # 设置摄像头参数
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.config.FRAME_WIDTH)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.config.FRAME_HEIGHT)
            self.cap.set(cv2.CAP_PROP_FPS, self.config.FPS)
            
            # 初始化通信连接
            self.init_communication()
            
            # 启动检测线程
            self.is_running = True
            self.detection_thread = threading.Thread(target=self._detection_loop, daemon=True)
            self.detection_thread.start()
            
            # 启动通信线程
            self.communication_thread = threading.Thread(target=self._communication_loop, daemon=True)
            self.communication_thread.start()
            
            logger.info("✅ 摄像头坐姿检测启动成功")
            return True
            
        except Exception as e:
            logger.error(f"❌ 启动检测失败: {e}")
            return False

    def init_communication(self):
        """初始化通信连接"""
        try:
            # 初始化串口连接
            self.serial_connection = serial.Serial(
                port=self.config.SERIAL_PORT,
                baudrate=self.config.SERIAL_BAUDRATE,
                timeout=1
            )
            logger.info("📡 串口连接建立成功")
        except Exception as e:
            logger.warning(f"⚠️ 串口连接失败: {e}")
        
        # 初始化WebSocket连接将在通信线程中处理

    def _detection_loop(self):
        """检测主循环"""
        session_start = time.time()
        total_detections = 0
        warning_count = 0
        fatigue_events = 0
        
        try:
            while self.is_running:
                ret, frame = self.cap.read()
                if not ret:
                    logger.warning("⚠️ 无法读取摄像头帧")
                    continue
                
                current_time = time.time()
                
                # 检查检测间隔
                if current_time - self.last_detection_time < self.config.DETECTION_INTERVAL:
                    continue
                
                self.last_detection_time = current_time
                self.frame_count += 1
                
                # 执行坐姿检测
                result = self.detect_posture(frame)
                if result:
                    total_detections += 1
                    
                    # 记录数据
                    self.record_posture_data(result)
                    
                    # 检查是否需要警告
                    if result.need_warning and self._should_give_warning(current_time):
                        self.trigger_warning(result)
                        warning_count += 1
                        self.last_warning_time = current_time
                    
                    # 发送实时数据
                    self.send_realtime_data(result)
                
                # 疲劳检测
                if current_time - self.last_fatigue_check >= self.config.FATIGUE_CHECK_INTERVAL:
                    fatigue_result = self.detect_fatigue(frame)
                    if fatigue_result and fatigue_result.fatigue_score > 0.7:
                        self.handle_fatigue_detection(fatigue_result)
                        fatigue_events += 1
                    self.last_fatigue_check = current_time
                
                # 显示检测结果（可选）
                if hasattr(self.config, 'SHOW_DISPLAY') and self.config.SHOW_DISPLAY:
                    display_frame = self.draw_detection_results(frame, result)
                    cv2.imshow('Smart Desk Posture Detection', display_frame)
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                        break
        
        except Exception as e:
            logger.error(f"❌ 检测循环异常: {e}")
        
        finally:
            # 保存会话记录
            self.save_session_record(session_start, time.time(), total_detections, warning_count, fatigue_events)

    def detect_posture(self, frame) -> Optional[PostureAnalysisResult]:
        """检测坐姿"""
        try:
            # 转换颜色空间
            rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            
            # 姿态检测
            pose_results = self.pose.process(rgb_frame)
            
            if not pose_results.pose_landmarks:
                return None
            
            # 提取关键点
            landmarks = self.extract_landmarks(pose_results.pose_landmarks)
            if not landmarks:
                return None
            
            # 计算坐姿度量
            metrics = self.calculate_posture_metrics(landmarks)
            
            # AI增强分析
            analysis_result = self.ai_analyzer.analyze_posture(metrics, self.landmark_history)
            
            # 个性化调整
            personalized_result = self.personalization_engine.adjust_analysis(analysis_result)
            
            # 添加到历史记录
            self.landmark_history.append(landmarks)
            self.metrics_history.append(metrics)
            
            return personalized_result
            
        except Exception as e:
            logger.error(f"❌ 坐姿检测异常: {e}")
            return None

    def extract_landmarks(self, pose_landmarks) -> Optional[PostureLandmarks]:
        """提取关键坐标点"""
        try:
            landmarks = pose_landmarks.landmark
            
            # 提取关键点坐标
            nose = (landmarks[0].x, landmarks[0].y)
            left_eye = (landmarks[1].x, landmarks[1].y)
            right_eye = (landmarks[2].x, landmarks[2].y)
            left_ear = (landmarks[7].x, landmarks[7].y)
            right_ear = (landmarks[8].x, landmarks[8].y)
            left_shoulder = (landmarks[11].x, landmarks[11].y)
            right_shoulder = (landmarks[12].x, landmarks[12].y)
            left_elbow = (landmarks[13].x, landmarks[13].y)
            right_elbow = (landmarks[14].x, landmarks[14].y)
            left_hip = (landmarks[23].x, landmarks[23].y)
            right_hip = (landmarks[24].x, landmarks[24].y)
            
            return PostureLandmarks(
                nose=nose,
                left_eye=left_eye,
                right_eye=right_eye,
                left_ear=left_ear,
                right_ear=right_ear,
                left_shoulder=left_shoulder,
                right_shoulder=right_shoulder,
                left_elbow=left_elbow,
                right_elbow=right_elbow,
                left_hip=left_hip,
                right_hip=right_hip,
                timestamp=time.time()
            )
            
        except Exception as e:
            logger.error(f"❌ 关键点提取异常: {e}")
            return None

    def calculate_posture_metrics(self, landmarks: PostureLandmarks) -> PostureMetrics:
        """计算坐姿度量"""
        try:
            # 计算头部倾斜角度
            head_tilt = self._calculate_head_tilt(landmarks)
            
            # 计算肩膀水平差
            shoulder_diff = self._calculate_shoulder_level_diff(landmarks)
            
            # 计算颈部前倾角度
            neck_forward = self._calculate_neck_forward_angle(landmarks)
            
            # 计算背部挺直度
            back_straight = self._calculate_back_straightness(landmarks)
            
            # 计算总体得分
            overall_score = self._calculate_overall_score(head_tilt, shoulder_diff, neck_forward, back_straight)
            
            # 计算置信度
            confidence = self._calculate_confidence(landmarks)
            
            return PostureMetrics(
                head_tilt_angle=head_tilt,
                shoulder_level_diff=shoulder_diff,
                neck_forward_angle=neck_forward,
                back_straightness=back_straight,
                overall_score=overall_score,
                confidence=confidence,
                timestamp=time.time()
            )
            
        except Exception as e:
            logger.error(f"❌ 度量计算异常: {e}")
            return PostureMetrics(0, 0, 0, 0, 0, 0, time.time())

    def _calculate_head_tilt(self, landmarks: PostureLandmarks) -> float:
        """计算头部倾斜角度"""
        # 使用双眼连线与水平线的夹角
        eye_dx = landmarks.right_eye[0] - landmarks.left_eye[0]
        eye_dy = landmarks.right_eye[1] - landmarks.left_eye[1]
        angle = math.degrees(math.atan2(eye_dy, eye_dx))
        return abs(angle)

    def _calculate_shoulder_level_diff(self, landmarks: PostureLandmarks) -> float:
        """计算肩膀水平差"""
        shoulder_dy = abs(landmarks.right_shoulder[1] - landmarks.left_shoulder[1])
        return shoulder_dy * 100  # 转换为像素差异

    def _calculate_neck_forward_angle(self, landmarks: PostureLandmarks) -> float:
        """计算颈部前倾角度"""
        # 使用耳朵和肩膀的位置关系
        ear_center_x = (landmarks.left_ear[0] + landmarks.right_ear[0]) / 2
        shoulder_center_x = (landmarks.left_shoulder[0] + landmarks.right_shoulder[0]) / 2
        forward_offset = abs(ear_center_x - shoulder_center_x) * 100
        return forward_offset

    def _calculate_back_straightness(self, landmarks: PostureLandmarks) -> float:
        """计算背部挺直度"""
        # 使用肩膀和臀部的垂直对齐度
        shoulder_center_x = (landmarks.left_shoulder[0] + landmarks.right_shoulder[0]) / 2
        hip_center_x = (landmarks.left_hip[0] + landmarks.right_hip[0]) / 2
        alignment_offset = abs(shoulder_center_x - hip_center_x) * 100
        return max(0, 100 - alignment_offset)  # 越直越接近100

    def _calculate_overall_score(self, head_tilt: float, shoulder_diff: float, neck_forward: float, back_straight: float) -> float:
        """计算总体坐姿得分"""
        # 头部倾斜评分
        head_score = max(0, 100 - (head_tilt / self.config.HEAD_TILT_THRESHOLD) * 50)
        
        # 肩膀水平评分
        shoulder_score = max(0, 100 - (shoulder_diff / self.config.SHOULDER_LEVEL_THRESHOLD) * 30)
        
        # 颈部前倾评分
        neck_score = max(0, 100 - (neck_forward / self.config.NECK_FORWARD_THRESHOLD) * 40)
        
        # 背部挺直评分
        back_score = back_straight
        
        # 加权平均
        overall_score = (head_score * 0.3 + shoulder_score * 0.2 + neck_score * 0.3 + back_score * 0.2)
        return min(100, max(0, overall_score))

    def _calculate_confidence(self, landmarks: PostureLandmarks) -> float:
        """计算检测置信度"""
        # 基于关键点的可见性和稳定性
        return 0.85  # 简化实现

    def detect_fatigue(self, frame) -> Optional[FatigueMetrics]:
        """检测疲劳状态"""
        try:
            rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            face_results = self.face_mesh.process(rgb_frame)
            
            if not face_results.multi_face_landmarks:
                return None
            
            face_landmarks = face_results.multi_face_landmarks[0]
            
            # 计算眼睛纵横比
            eye_ratio = self._calculate_eye_aspect_ratio(face_landmarks)
            
            # 计算眨眼频率
            blink_freq = self._calculate_blink_frequency()
            
            # 计算头部稳定性
            head_stability = self._calculate_head_stability()
            
            # 计算注意力水平
            attention_level = self._calculate_attention_level(eye_ratio, head_stability)
            
            # 计算疲劳得分
            fatigue_score = self._calculate_fatigue_score(eye_ratio, blink_freq, head_stability, attention_level)
            
            fatigue_metrics = FatigueMetrics(
                eye_aspect_ratio=eye_ratio,
                blink_frequency=blink_freq,
                head_stability=head_stability,
                attention_level=attention_level,
                fatigue_score=fatigue_score,
                timestamp=time.time()
            )
            
            self.fatigue_history.append(fatigue_metrics)
            return fatigue_metrics
            
        except Exception as e:
            logger.error(f"❌ 疲劳检测异常: {e}")
            return None

    def _calculate_eye_aspect_ratio(self, face_landmarks) -> float:
        """计算眼睛纵横比"""
        # 简化实现，实际应该使用具体的眼部关键点
        return 0.3  # 正常眼睛纵横比

    def _calculate_blink_frequency(self) -> float:
        """计算眨眼频率"""
        # 基于历史数据计算
        if len(self.fatigue_history) < 10:
            return 15.0  # 正常眨眼频率
        
        # 分析最近的眼睛纵横比变化
        recent_ratios = [f.eye_aspect_ratio for f in list(self.fatigue_history)[-10:]]
        blinks = sum(1 for i in range(1, len(recent_ratios)) 
                    if recent_ratios[i-1] > 0.25 and recent_ratios[i] < 0.2)
        return blinks * 6  # 转换为每分钟次数

    def _calculate_head_stability(self) -> float:
        """计算头部稳定性"""
        if len(self.landmark_history) < 5:
            return 1.0
        
        # 计算最近几帧的头部位置变化
        recent_positions = [(l.nose[0], l.nose[1]) for l in list(self.landmark_history)[-5:]]
        if len(recent_positions) < 2:
            return 1.0
        
        total_movement = 0
        for i in range(1, len(recent_positions)):
            dx = recent_positions[i][0] - recent_positions[i-1][0]
            dy = recent_positions[i][1] - recent_positions[i-1][1]
            movement = math.sqrt(dx*dx + dy*dy)
            total_movement += movement
        
        avg_movement = total_movement / (len(recent_positions) - 1)
        stability = max(0, 1 - avg_movement * 10)  # 运动越小稳定性越高
        return stability

    def _calculate_attention_level(self, eye_ratio: float, head_stability: float) -> float:
        """计算注意力水平"""
        # 综合眼睛状态和头部稳定性
        eye_attention = 1.0 if eye_ratio > 0.25 else 0.5  # 眼睛睁开程度
        head_attention = head_stability
        return (eye_attention + head_attention) / 2

    def _calculate_fatigue_score(self, eye_ratio: float, blink_freq: float, head_stability: float, attention_level: float) -> float:
        """计算疲劳得分"""
        # 眼睛疲劳指标
        eye_fatigue = 1.0 - min(1.0, eye_ratio / 0.3)
        
        # 眨眼频率异常指标
        normal_blink_freq = 15.0
        blink_fatigue = abs(blink_freq - normal_blink_freq) / normal_blink_freq
        
        # 注意力分散指标
        attention_fatigue = 1.0 - attention_level
        
        # 头部不稳定指标
        stability_fatigue = 1.0 - head_stability
        
        # 综合疲劳得分
        overall_fatigue = (eye_fatigue * 0.4 + blink_fatigue * 0.2 + 
                          attention_fatigue * 0.2 + stability_fatigue * 0.2)
        
        return min(1.0, max(0.0, overall_fatigue))

    def _should_give_warning(self, current_time: float) -> bool:
        """判断是否应该给出警告"""
        return current_time - self.last_warning_time >= self.config.WARNING_INTERVAL

    def trigger_warning(self, result: PostureAnalysisResult):
        """触发坐姿警告"""
        logger.warning(f"⚠️ 坐姿警告: {result.status} - {result.voice_feedback}")
        
        # 发送警告到主系统
        warning_data = {
            'type': 'posture_warning',
            'status': result.status,
            'score': result.score,
            'issues': result.issues,
            'suggestions': result.suggestions,
            'voice_feedback': result.voice_feedback,
            'severity': result.severity,
            'timestamp': result.timestamp
        }
        
        self.send_to_main_system(warning_data)

    def handle_fatigue_detection(self, fatigue_result: FatigueMetrics):
        """处理疲劳检测结果"""
        logger.warning(f"😴 疲劳检测: 疲劳得分 {fatigue_result.fatigue_score:.2f}")
        
        # 生成疲劳提醒消息
        fatigue_message = self._generate_fatigue_message(fatigue_result)
        
        # 发送疲劳警告
        fatigue_data = {
            'type': 'fatigue_warning',
            'fatigue_score': fatigue_result.fatigue_score,
            'eye_ratio': fatigue_result.eye_aspect_ratio,
            'attention_level': fatigue_result.attention_level,
            'message': fatigue_message,
            'timestamp': fatigue_result.timestamp
        }
        
        self.send_to_main_system(fatigue_data)

    def _generate_fatigue_message(self, fatigue_result: FatigueMetrics) -> str:
        """生成疲劳提醒消息"""
        if fatigue_result.fatigue_score > 0.8:
            return "检测到严重疲劳，建议您立即休息10-15分钟，眺望远方放松眼睛。"
        elif fatigue_result.fatigue_score > 0.6:
            return "您看起来有些疲劳，建议稍作休息，站起来活动一下。"
        else:
            return "注意劳逸结合，保持良好的学习状态。"

    def send_to_main_system(self, data: dict):
        """发送数据到主系统"""
        try:
            if self.serial_connection and self.serial_connection.is_open:
                message = f"CAMERA_RESULT:{json.dumps(data)}\n"
                self.serial_connection.write(message.encode())
                logger.debug(f"📡 发送到主系统: {data['type']}")
        except Exception as e:
            logger.error(f"❌ 发送数据到主系统失败: {e}")

    def send_realtime_data(self, result: PostureAnalysisResult):
        """发送实时数据"""
        realtime_data = {
            'type': 'realtime_posture',
            'status': result.status,
            'score': result.score,
            'timestamp': result.timestamp,
            'frame_count': self.frame_count
        }
        
        # 添加到通信队列
        self.communication_queue.put(realtime_data)

    def record_posture_data(self, result: PostureAnalysisResult):
        """记录坐姿数据到数据库"""
        try:
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    INSERT INTO posture_records 
                    (timestamp, head_tilt, shoulder_diff, neck_forward, back_straight, 
                     overall_score, status, suggestions, need_warning)
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    result.timestamp, 0, 0, 0, 0,  # 暂时使用占位值
                    result.score, result.status,
                    json.dumps(result.suggestions),
                    result.need_warning
                ))
                conn.commit()
        except Exception as e:
            logger.error(f"❌ 记录坐姿数据失败: {e}")

    def save_session_record(self, start_time: float, end_time: float, detections: int, warnings: int, fatigue_events: int):
        """保存会话记录"""
        try:
            avg_score = 0
            if self.metrics_history:
                avg_score = sum(m.overall_score for m in self.metrics_history) / len(self.metrics_history)
            
            with sqlite3.connect(self.db_path) as conn:
                cursor = conn.cursor()
                cursor.execute('''
                    INSERT INTO session_records 
                    (session_start, session_end, total_detections, average_score, warning_count, fatigue_events)
                    VALUES (?, ?, ?, ?, ?, ?)
                ''', (start_time, end_time, detections, avg_score, warnings, fatigue_events))
                conn.commit()
                
            logger.info(f"📊 会话记录已保存: 检测{detections}次, 平均得分{avg_score:.1f}, 警告{warnings}次")
        except Exception as e:
            logger.error(f"❌ 保存会话记录失败: {e}")

    def _communication_loop(self):
        """通信循环"""
        try:
            while self.is_running:
                try:
                    # 处理WebSocket通信
                    if not self.communication_queue.empty():
                        data = self.communication_queue.get()
                        self._send_to_wechat(data)
                    
                    # 处理串口命令
                    if self.serial_connection and self.serial_connection.is_open:
                        if self.serial_connection.in_waiting:
                            command = self.serial_connection.readline().decode().strip()
                            self._handle_serial_command(command)
                    
                    time.sleep(0.1)
                    
                except Exception as e:
                    logger.error(f"❌ 通信循环异常: {e}")
                    time.sleep(1)
        except Exception as e:
            logger.error(f"❌ 通信线程异常: {e}")

    def _send_to_wechat(self, data: dict):
        """发送数据到微信小程序"""
        # 这里应该实现WebSocket发送逻辑
        logger.debug(f"📱 发送到微信: {data['type']}")

    def _handle_serial_command(self, command: str):
        """处理串口命令"""
        if command.startswith("CAMERA_REQUEST:"):
            # 主系统请求摄像头检测
            distance_str = command.replace("CAMERA_REQUEST:", "")
            try:
                ultrasonic_distance = float(distance_str)
                # 结合超声波距离进行联合分析
                self._perform_joint_analysis(ultrasonic_distance)
            except ValueError:
                logger.warning(f"⚠️ 无效的距离数据: {distance_str}")

    def _perform_joint_analysis(self, ultrasonic_distance: float):
        """执行联合分析"""
        if not self.metrics_history:
            return
        
        latest_metrics = self.metrics_history[-1]
        
        # 结合超声波距离和摄像头检测结果
        joint_analysis = {
            'type': 'joint_analysis',
            'camera_score': latest_metrics.overall_score,
            'ultrasonic_distance': ultrasonic_distance,
            'combined_assessment': self._generate_combined_assessment(latest_metrics, ultrasonic_distance),
            'timestamp': time.time()
        }
        
        self.send_to_main_system(joint_analysis)

    def _generate_combined_assessment(self, metrics: PostureMetrics, distance: float) -> dict:
        """生成联合评估结果"""
        # 距离评估
        distance_score = 100
        if distance < 30:
            distance_score = max(0, 100 - (30 - distance) * 3)
        elif distance > 50:
            distance_score = max(0, 100 - (distance - 50) * 2)
        
        # 综合得分
        combined_score = (metrics.overall_score * 0.7 + distance_score * 0.3)
        
        # 生成建议
        suggestions = []
        if distance < 30:
            suggestions.append("距离过近，请向后调整座椅")
        elif distance > 50:
            suggestions.append("距离过远，请向前调整座椅")
        
        if metrics.overall_score < 70:
            suggestions.append("请注意坐姿，保持背部挺直")
        
        return {
            'combined_score': combined_score,
            'distance_score': distance_score,
            'camera_score': metrics.overall_score,
            'suggestions': suggestions,
            'status': 'excellent' if combined_score >= 90 else 'good' if combined_score >= 70 else 'poor'
        }

    def draw_detection_results(self, frame, result: Optional[PostureAnalysisResult]):
        """绘制检测结果"""
        if not result:
            return frame
        
        # 绘制坐姿信息
        cv2.putText(frame, f"Status: {result.status}", (10, 30), 
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        cv2.putText(frame, f"Score: {result.score:.1f}", (10, 60), 
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        
        # 绘制建议
        y_offset = 90
        for i, suggestion in enumerate(result.suggestions[:3]):  # 最多显示3条建议
            cv2.putText(frame, suggestion[:30], (10, y_offset + i * 25), 
                       cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 1)
        
        return frame

    def stop_detection(self):
        """停止检测"""
        logger.info("🛑 停止摄像头坐姿检测...")
        
        self.is_running = False
        
        if hasattr(self, 'detection_thread'):
            self.detection_thread.join(timeout=5)
        
        if hasattr(self, 'communication_thread'):
            self.communication_thread.join(timeout=5)
        
        if self.cap:
            self.cap.release()
        
        if self.serial_connection and self.serial_connection.is_open:
            self.serial_connection.close()
        
        cv2.destroyAllWindows()
        
        logger.info("✅ 摄像头坐姿检测已停止")

# ========== AI分析引擎 ==========

class AIPostureAnalyzer:
    """AI坐姿分析引擎"""
    
    def __init__(self):
        self.api_key = PostureConfig.AI_API_KEY
        self.api_url = PostureConfig.AI_API_URL
    
    def analyze_posture(self, metrics: PostureMetrics, history: deque) -> PostureAnalysisResult:
        """AI分析坐姿"""
        try:
            # 基础分析
            basic_result = self._basic_analysis(metrics)
            
            # 如果有API配置，进行AI增强分析
            if self.api_key and self.api_key != 'your-openai-api-key':
                enhanced_result = self._ai_enhanced_analysis(metrics, history, basic_result)
                return enhanced_result
            else:
                return basic_result
                
        except Exception as e:
            logger.error(f"❌ AI分析异常: {e}")
            return self._basic_analysis(metrics)
    
    def _basic_analysis(self, metrics: PostureMetrics) -> PostureAnalysisResult:
        """基础分析"""
        issues = []
        suggestions = []
        
        # 分析各项指标
        if metrics.head_tilt_angle > PostureConfig.HEAD_TILT_THRESHOLD:
            issues.append("头部倾斜过度")
            suggestions.append("请调整头部位置，保持头部正直")
        
        if metrics.shoulder_level_diff > PostureConfig.SHOULDER_LEVEL_THRESHOLD:
            issues.append("肩膀不平衡")
            suggestions.append("请调整肩膀高度，保持水平")
        
        if metrics.neck_forward_angle > PostureConfig.NECK_FORWARD_THRESHOLD:
            issues.append("颈部前倾")
            suggestions.append("请将头部向后收，避免颈部前倾")
        
        if metrics.back_straightness < PostureConfig.BACK_STRAIGHT_THRESHOLD:
            issues.append("背部弯曲")
            suggestions.append("请挺直背部，保持脊柱自然曲线")
        
        # 确定状态和严重程度
        if metrics.overall_score >= 90:
            status = "excellent"
            severity = "none"
            voice_feedback = "坐姿非常棒，请继续保持！"
            need_warning = False
        elif metrics.overall_score >= 70:
            status = "good"
            severity = "mild"
            voice_feedback = "坐姿总体良好，稍作调整会更好。"
            need_warning = False
        elif metrics.overall_score >= 50:
            status = "fair"
            severity = "moderate"
            voice_feedback = "坐姿需要调整，请注意保持正确姿势。"
            need_warning = True
        else:
            status = "poor"
            severity = "severe"
            voice_feedback = "坐姿问题较多，请立即调整为正确姿势。"
            need_warning = True
        
        if not suggestions:
            suggestions.append("坐姿良好，继续保持")
        
        return PostureAnalysisResult(
            status=status,
            score=metrics.overall_score,
            issues=issues,
            suggestions=suggestions,
            severity=severity,
            voice_feedback=voice_feedback,
            need_warning=need_warning,
            timestamp=metrics.timestamp
        )
    
    def _ai_enhanced_analysis(self, metrics: PostureMetrics, history: deque, basic_result: PostureAnalysisResult) -> PostureAnalysisResult:
        """AI增强分析"""
        try:
            # 构建AI请求
            prompt = self._build_ai_prompt(metrics, history, basic_result)
            
            response = requests.post(
                self.api_url,
                headers={
                    'Authorization': f'Bearer {self.api_key}',
                    'Content-Type': 'application/json'
                },
                json={
                    'model': 'gpt-3.5-turbo',
                    'messages': [
                        {'role': 'system', 'content': '你是一个专业的坐姿健康顾问，请根据检测数据提供专业建议。'},
                        {'role': 'user', 'content': prompt}
                    ],
                    'max_tokens': 200,
                    'temperature': 0.7
                },
                timeout=10
            )
            
            if response.status_code == 200:
                ai_response = response.json()
                enhanced_feedback = ai_response['choices'][0]['message']['content']
                
                # 更新语音反馈
                basic_result.voice_feedback = enhanced_feedback[:100]  # 限制长度
                
            return basic_result
            
        except Exception as e:
            logger.error(f"❌ AI增强分析失败: {e}")
            return basic_result
    
    def _build_ai_prompt(self, metrics: PostureMetrics, history: deque, basic_result: PostureAnalysisResult) -> str:
        """构建AI提示词"""
        prompt = f"""
        当前坐姿检测数据：
        - 总体得分：{metrics.overall_score:.1f}
        - 头部倾斜：{metrics.head_tilt_angle:.1f}度
        - 肩膀水平差：{metrics.shoulder_level_diff:.1f}
        - 颈部前倾：{metrics.neck_forward_angle:.1f}
        - 背部挺直度：{metrics.back_straightness:.1f}
        - 基础状态：{basic_result.status}
        - 发现问题：{', '.join(basic_result.issues)}
        
        请提供简洁专业的坐姿改进建议，控制在50字以内。
        """
        return prompt

# ========== 个性化引擎 ==========

class PersonalizationEngine:
    """个性化适应引擎"""
    
    def __init__(self):
        self.user_profile = self._load_user_profile()
        self.adaptation_history = deque(maxlen=100)
    
    def adjust_analysis(self, result: PostureAnalysisResult) -> PostureAnalysisResult:
        """个性化调整分析结果"""
        # 基于用户历史数据调整阈值和建议
        adjusted_result = result
        
        # 记录适应历史
        self.adaptation_history.append({
            'score': result.score,
            'status': result.status,
            'timestamp': result.timestamp
        })
        
        return adjusted_result
    
    def _load_user_profile(self) -> dict:
        """加载用户配置文件"""
        try:
            with open('data/user_profile.json', 'r', encoding='utf-8') as f:
                return json.load(f)
        except FileNotFoundError:
            return {
                'height': 170,
                'age': 25,
                'preferences': {},
                'adaptation_factor': 1.0
            }

# ========== 主程序入口 ==========

def main():
    """主程序"""
    logger.info("🚀 启动摄像头坐姿检测系统...")
    
    try:
        # 创建检测器
        detector = CameraPostureDetector()
        
        # 启动检测
        if detector.start_detection():
            logger.info("✅ 系统运行中，按 Ctrl+C 停止...")
            
            try:
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                logger.info("📋 收到停止信号...")
        
        # 停止检测
        detector.stop_detection()
        
    except Exception as e:
        logger.error(f"❌ 程序异常: {e}")
    
    logger.info("👋 摄像头坐姿检测系统已退出")

if __name__ == "__main__":
    main()